package BinaryTree;

import java.util.Stack;

/**
 * @author Liaorun
 */
public class PreInPosTraversal {

    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int value) {
            this.value = value;
        }
    }

    public static void preOrderRecur(Node head) {
        if (head == null) {
            return;
        }


        System.out.print(head.value + " ");
        preOrderRecur(head.left);
        preOrderRecur(head.right);
    }

    public static void inOrderRecur(Node head) {
        if (head == null) {
            return;
        }

        inOrderRecur(head.left);
        System.out.print(head.value + " ");
        inOrderRecur(head.right);
    }

    public static void inOrderUnRecur(Node head) {
        System.out.print("in-order: ");

        if (head != null) {
            Stack<Node> stack = new Stack<>();
            while (!stack.isEmpty() || head != null) {
                if (head != null) {
                    // 将左边界全部进栈

                    // 当前节点不为空，就压到栈中
                    stack.push(head);
                    // 当前节点改为左节点
                    head = head.left;
                } else {
                    // 当前节点为空
                    // 栈中弹出一个元素
                    head = stack.pop();
                    // 打印
                    System.out.print(head.value + " ");
                    // 当前节点改为右节点
                    head = head.right;
                }
            }
        }

        System.out.println();
    }

    public static void posOrderRecur(Node head) {
        if (head == null) {
            return;
        }

        posOrderRecur(head.left);
        posOrderRecur(head.right);
        System.out.print(head.value + " ");

    }

    public static void preOrderUnRecur(Node head) {
        System.out.println("pre-order");

        if (head != null) {
            Stack<Node> stack = new Stack<>();

            stack.add(head);

            while (!stack.isEmpty()) {
                head = stack.pop();
                System.out.print(head.value + " ");
                if (head.right != null) {
                    stack.push(head.right);
                }
                if (head.left != null) {
                    stack.push(head.left);
                }
            }
        }
        System.out.println();
    }

    /**
     * 利用两个栈完成二叉树的后续遍历
     *
     * @param head 二叉树的根节点
     */
    public static void posOrderRecur1(Node head) {
        System.out.println("pos-order: ");
        if (head != null) {
            // 按照头右左的顺序搜集
            Stack<Node> s1 = new Stack<>();
            // 按照左右头的顺序搜集
            Stack<Node> s2 = new Stack<>();

            s1.push(head);
            while (!s1.isEmpty()) {
                // 第一个弹栈
                head = s1.pop();
                // 将第一个栈弹出的元素放到第二个栈
                s2.push(head);

                // 向第一个栈放左节点
                if (head.left != null) {
                    s1.push(head.left);
                }
                // 向第二个栈放右节点
                if (head.right != null) {
                    s1.push(head.right);
                }
            }

            // 弹出第二个栈的全部元素并打印
            while (!s2.isEmpty()) {
                System.out.println(s2.pop().value + " ");
            }
        }

        System.out.println();
    }

    public static void main(String[] args) {
        Node head = new Node(5);
        head.left = new Node(3);
        head.right = new Node(8);

        head.left.left = new Node(2);
        head.left.right = new Node(4);

        head.left.left.left = new Node(1);

        head.right.left = new Node(7);
        head.right.left.left = new Node(6);

        head.right.right = new Node(10);
        head.right.right.left = new Node(9);
        head.right.right.right = new Node(11);

        // recursive
        System.out.println("===== recursive ====");
        System.out.println("pre-order");
        preOrderRecur(head);
        System.out.println("in-order");
        inOrderRecur(head);
        System.out.println("pos-order");
        posOrderRecur(head);
    }
}
